<?php

	namespace org\tekuna\test\core\configuration;


	use \PHPUnit_Framework_TestCase;

	use org\tekuna\core\configuration\XmlConfiguration;
	use org\tekuna\core\context\Context;


	class XmlConfigurationTest extends PHPUnit_Framework_TestCase {

		public function testLoadConfigAfterCallLoad() {

			// build config
			$objConfig = new XmlConfiguration(__DIR__ . DIRECTORY_SEPARATOR . 'xml' . DIRECTORY_SEPARATOR . 'testLoadConfigAfterCallLoad.xml');

			// nothing loaded yet
			$this -> assertNull($objConfig -> getRootElement());

			// call load mathod
			$objConfig -> loadConfiguration(new Context());

			// now something loaded
			$this -> assertNotNull($objConfig -> getRootElement());
		}


		private function loadTestConfig($sFilename) {

			$sFilename = __DIR__ . DIRECTORY_SEPARATOR . 'xml' . DIRECTORY_SEPARATOR . $sFilename;
			$sCoreNamespace = 'http://tekuna.org/testcore/';

			$objConfig = new XmlConfiguration($sFilename, $sCoreNamespace);
			$objConfig -> loadConfiguration(new Context());
			return $objConfig;
		}


		public function testLoadNamespaces() {

			$objConfig = $this -> loadTestConfig('testLoadNamespaces.xml');
			$objRootElement = $objConfig -> getRootElement();

			// there were 9 child elements loaded
			$this -> assertEquals(9, count($objRootElement -> getChildElements()));

			$arrChildElements = $objRootElement -> getChildElements();
			$ns1 = 'http://tekuna.org/test/ns1';
			$ns2 = 'http://tekuna.org/test/ns2';
			$ns3 = 'http://tekuna.org/test/ns3';

			// compare all those elements - yes this is necessary...
			$this -> assertEquals($ns1, $arrChildElements[0] -> getAspect());
			$this -> assertEquals('ns1Elem', $arrChildElements[0] -> getName());
			$this -> assertEquals('', $arrChildElements[0] -> getValue());
			$this -> assertEquals(array(), $arrChildElements[0] -> getAttributes());

			$this -> assertEquals($ns1, $arrChildElements[1] -> getAspect());
			$this -> assertEquals('ns1Elem', $arrChildElements[1] -> getName());
			$this -> assertEquals('ns1ElemValue', $arrChildElements[1] -> getValue());
			$this -> assertEquals(1, count($arrChildElements[1] -> getAttributes()));
			$this -> assertNotNull($arrChildElements[1] -> getAttribute($ns1, 'ns1Attr'));
			$this -> assertEquals('ns1AttrValue', $arrChildElements[1] -> getAttribute($ns1, 'ns1Attr') -> getValue());

			$this -> assertEquals($ns2, $arrChildElements[2] -> getAspect());
			$this -> assertEquals('ns2Elem', $arrChildElements[2] -> getName());
			$this -> assertEquals('', $arrChildElements[2] -> getValue());
			$this -> assertEquals(array(), $arrChildElements[2] -> getAttributes());

			$this -> assertEquals($ns2, $arrChildElements[3] -> getAspect());
			$this -> assertEquals('ns2Elem', $arrChildElements[3] -> getName());
			$this -> assertEquals('ns2ElemValue', $arrChildElements[3] -> getValue());
			$this -> assertEquals(1, count($arrChildElements[3] -> getAttributes()));
			$this -> assertNotNull($arrChildElements[3] -> getAttribute($ns2, 'ns2Attr'));
			$this -> assertEquals('ns2AttrValueImplicit', $arrChildElements[3] -> getAttribute($ns2, 'ns2Attr') -> getValue());

			$this -> assertEquals($ns2, $arrChildElements[4] -> getAspect());
			$this -> assertEquals('ns2Elem', $arrChildElements[4] -> getName());
			$this -> assertEquals('ns2ElemValue', $arrChildElements[4] -> getValue());
			$this -> assertEquals(1, count($arrChildElements[4] -> getAttributes()));
			$this -> assertNotNull($arrChildElements[4] -> getAttribute($ns2, 'ns2Attr'));
			$this -> assertEquals('ns2AttrValueExplicit', $arrChildElements[4] -> getAttribute($ns2, 'ns2Attr') -> getValue());

			$this -> assertEquals($ns3, $arrChildElements[5] -> getAspect());
			$this -> assertEquals('ns3Elem', $arrChildElements[5] -> getName());
			$this -> assertEquals('', $arrChildElements[5] -> getValue());
			$this -> assertEquals(array(), $arrChildElements[5] -> getAttributes());

			$this -> assertEquals($ns3, $arrChildElements[6] -> getAspect());
			$this -> assertEquals('ns3Elem', $arrChildElements[6] -> getName());
			$this -> assertEquals('ns3ElemValue', $arrChildElements[6] -> getValue());
			$this -> assertEquals(1, count($arrChildElements[6] -> getAttributes()));
			$this -> assertNotNull($arrChildElements[6] -> getAttribute($ns3, 'ns3Attr'));
			$this -> assertEquals('ns3AttrValueImplicit', $arrChildElements[6] -> getAttribute($ns3, 'ns3Attr') -> getValue());

			$this -> assertEquals($ns3, $arrChildElements[7] -> getAspect());
			$this -> assertEquals('ns3Elem', $arrChildElements[7] -> getName());
			$this -> assertEquals('ns3ElemValue', $arrChildElements[7] -> getValue());
			$this -> assertEquals(1, count($arrChildElements[7] -> getAttributes()));
			$this -> assertNotNull($arrChildElements[7] -> getAttribute($ns3, 'ns3Attr'));
			$this -> assertEquals('ns3AttrValueExplicit', $arrChildElements[7] -> getAttribute($ns3, 'ns3Attr') -> getValue());

			$this -> assertEquals($ns1, $arrChildElements[8] -> getAspect());
			$this -> assertEquals('ns1nest', $arrChildElements[8] -> getName());
			$this -> assertEquals("ns1\n\t\t\n\t\t.ns1", $arrChildElements[8] -> getValue());
			$this -> assertEquals(array(), $arrChildElements[8] -> getAttributes());

			$arrElem9Childs = $arrChildElements[8] -> getChildElements();
			$this -> assertEquals(1, count($arrElem9Childs));
			$this -> assertEquals($ns2, $arrElem9Childs[0] -> getAspect());
			$this -> assertEquals('ns2nest', $arrElem9Childs[0] -> getName());
			$this -> assertEquals("ns2\n\t\t\t\n\t\t\t.ns2", $arrElem9Childs[0] -> getValue());
			$this -> assertEquals(0, count($arrElem9Childs[0] -> getAttributes()));

			$arrElem9Elem0Childs = $arrElem9Childs[0] -> getChildElements();
			$this -> assertEquals(1, count($arrElem9Elem0Childs));
			$this -> assertEquals($ns3, $arrElem9Elem0Childs[0] -> getAspect());
			$this -> assertEquals('ns3nest', $arrElem9Elem0Childs[0] -> getName());
			$this -> assertEquals('', $arrElem9Elem0Childs[0] -> getValue());

			$arrElem9Elem0Attributes = $arrElem9Elem0Childs[0] -> getAttributes();
			$this -> assertEquals(2, count($arrElem9Elem0Attributes));
			$this -> assertEquals($ns2, $arrElem9Elem0Attributes[0] -> getAspect());
			$this -> assertEquals('ns2Value', $arrElem9Elem0Attributes[0] -> getValue());
			$this -> assertEquals($ns3, $arrElem9Elem0Attributes[1] -> getAspect());
			$this -> assertEquals('ns3Value', $arrElem9Elem0Attributes[1] -> getValue());
		}


		/**
		 * @expectedException org\tekuna\core\configuration\ConfigurationException
		 */
		public function testNoRootElement() {

			$objConfig = $this -> loadTestConfig('testNoRootElement.xml');
		}


		/**
		 * @expectedException org\tekuna\core\configuration\ConfigurationException
		 */
		public function testFileDoesNotExist() {

			$objConfig = $this -> loadTestConfig('testFileDoesNotExist.xml');
		}


		public function testRemoveXsiSchemaLocation() {

			$objConfig = $this -> loadTestConfig('testRemoveXsiSchemaLocation.xml');
			$objRootElement = $objConfig -> getRootElement();

			$this -> assertTrue($objRootElement -> hasAttribute('http://tekuna.org/test/', 'testAttribute'));
			$this -> assertFalse($objRootElement -> hasAttribute('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation'));
		}


		public function testInclude() {

			$objConfig = $this -> loadTestConfig('testInclude.xml');
			$objRootElement = $objConfig -> getRootElement();

			// check existence of childs
			$this -> assertTrue($objRootElement -> hasChildElement('http://tekuna.org/test/', 'testNode1'));
			$this -> assertTrue($objRootElement -> hasChildElement('http://tekuna.org/test/', 'testNode2'));
			$this -> assertTrue($objRootElement -> hasChildElement('http://tekuna.org/test/', 'testNode3'));
			$this -> assertTrue($objRootElement -> hasChildElement('core', 'include'));

			// check order of childs
			$arrChildElements = $objRootElement -> getChildElements();
			$this -> assertEquals(6, count($arrChildElements));

			$this -> assertEquals('http://tekuna.org/test/', $arrChildElements[0] -> getAspect());
			$this -> assertEquals('testNode1', $arrChildElements[0] -> getName());

			$this -> assertEquals('core', $arrChildElements[1] -> getAspect());
			$this -> assertEquals('include', $arrChildElements[1] -> getName());

			$this -> assertEquals('http://tekuna.org/test/', $arrChildElements[2] -> getAspect());
			$this -> assertEquals('testNode2', $arrChildElements[2] -> getName());

			$this -> assertEquals('core', $arrChildElements[3] -> getAspect());
			$this -> assertEquals('include', $arrChildElements[3] -> getName());

			$this -> assertEquals('http://tekuna.org/test/', $arrChildElements[4] -> getAspect());
			$this -> assertEquals('testNode3', $arrChildElements[4] -> getName());

			$this -> assertEquals('http://tekuna.org/test/', $arrChildElements[5] -> getAspect());
			$this -> assertEquals('testNode4', $arrChildElements[5] -> getName());
		}


		public function testCyclicInclude() {

			$objConfig = $this -> loadTestConfig('testCyclicInclude.xml');
			$objRootElement = $objConfig -> getRootElement();

			// there was no infinit loop while loading

			// all includes are there
			$this -> assertEquals(5, count($objRootElement -> getChildElements()));
		}
		
		
// not done by the XMLConfiguration anymore but by the Application now.
//
//		public function testNamespaceMapping() {
//
//			$objConfig = $this -> loadTestConfig('testNamespaceMapping.xml');
//			$objRootElement = $objConfig -> getRootElement();
//
//			// all elements are there (even the config-handlers)
//			$this -> assertEquals(7, count($objRootElement ->getChildElements()));
//
//			// the mapped or not mapped aspects are there
//			$this -> assertTrue($objRootElement -> hasChildElement('http://tekuna.org/notmapped/', 'testElem'));
//
//			$this -> assertFalse($objRootElement -> hasChildElement('http://tekuna.org/normal/', 'testElem'));
//			$this -> assertTrue($objRootElement -> hasChildElement('normalAspect', 'testElem'));
//
//			$this -> assertFalse($objRootElement -> hasChildElement('http://tekuna.org/merged/1/', 'testElem1'));
//			$this -> assertTrue($objRootElement -> hasChildElement('mergedAspect', 'testElem1'));
//
//			$this -> assertFalse($objRootElement -> hasChildElement('http://tekuna.org/merged/2/', 'testElem2'));
//			$this -> assertTrue($objRootElement -> hasChildElement('mergedAspect', 'testElem2'));
//		}
	}
